home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / customs / rmt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  23.3 KB  |  984 lines

  1. /*-
  2.  * rmt.c --
  3.  *    Functions to handle the exportation of targets using the
  4.  *    customs daemon.
  5.  *
  6.  * Copyright (c) 1988, 1989 by the Regents of the University of California
  7.  * Copyright (c) 1988, 1989 by Adam de Boor
  8.  * Copyright (c) 1989 by Berkeley Softworks
  9.  *
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any non-commercial purpose
  12.  * and without fee is hereby granted, provided that the above copyright
  13.  * notice appears in all copies.  The University of California,
  14.  * Berkeley Softworks and Adam de Boor make no representations about
  15.  * the suitability of this software for any purpose.  It is provided
  16.  * "as is" without express or implied warranty.
  17.  *
  18.  * Interface:
  19.  *    Rmt_Init              Initialize things for this module
  20.  *
  21.  *    Rmt_AddServer            Add the given name as the address of
  22.  *                          an export server.
  23.  *
  24.  *    Rmt_ReExport            Re-export a job that has come home to roost.
  25.  *
  26.  *    Rmt_Begin             Prepare to export another job and tell
  27.  *                          if it can actually be exported.
  28.  *
  29.  *    Rmt_Exec              Execute the given shell with argument vector
  30.  *                          elsewhere.
  31.  *
  32.  *    Rmt_LastID            Return an unique identifier for the last
  33.  *                          job exported.
  34.  *
  35.  *    Rmt_Done              Take note that a remote job has finished.
  36.  *
  37.  *    Rmt_Watch               Pay attention to a stream.
  38.  *
  39.  *    Rmt_Ignore              Ignore a stream
  40.  *
  41.  *    Rmt_Wait                Wait for something to happen
  42.  *
  43.  *    Rmt_Signal              Deliver a signal to a job.
  44.  */
  45. #ifndef lint
  46. static char *rcsid =
  47. "$Id: rmt.c,v 1.12 89/11/14 17:49:42 adam Exp $ SPRITE (Berkeley)";
  48. #endif lint
  49.  
  50. #include    <sys/time.h>
  51. #include    <sys/fcntl.h>
  52. #include    <sys/file.h>
  53. #include    <stdio.h>
  54. #include    <sys/wait.h>
  55. #include    <errno.h>
  56. extern int  errno;
  57.  
  58. #include    "make.h"
  59. #include    "job.h"
  60.  
  61. #include    "customs.h"
  62.  
  63. /*
  64.  * Macro to deal with incompatible calling conventions between gcc and cc on
  65.  * a sparc (gcc passes the address in a register, since the structure is
  66.  * small enough, while cc still passes the address).
  67.  */
  68. #if defined(__GNUC__) && defined(sparc)
  69. #define InetNtoA(addr)    inet_ntoa(&(addr))
  70. #else
  71. #define InetNtoA(addr)    inet_ntoa(addr)
  72. #endif
  73.  
  74. /*
  75.  * Private data attached to each job exported by this module. The address of
  76.  * such a structure is returned as the remote ID for the job.
  77.  */
  78. typedef struct {
  79.     ExportPermit  permit;       /* Permit under which job was exported */
  80.     int              rmtFd;        /* FD of stream to remote job. Needed if
  81.                  * usePipes is FALSE */
  82.     int              cmdFd;      /* FD of file containing commands */
  83. } CustomsPriv;
  84.  
  85. static char           cwd[1024];  /* The current working directory */
  86. static Boolean          noAgent;    /* TRUE if agent not present */
  87.  
  88. /*
  89.  * From customslib.c
  90.  */
  91. extern int            customs_Socket;    /* Socket opened by Customs calls */
  92. extern struct timeval    customs_RetryTimeOut;    /* Default retry interval */
  93. extern struct sockaddr_in customs_AgentAddr;
  94.  
  95. /*
  96.  * For Make-mode exportation.
  97.  */
  98. static int returnFD;
  99. static int exportFD;
  100. static ExportPermit permit;
  101.  
  102. #include    <sys/ioctl.h>
  103. #include    <netdb.h>
  104.  
  105. /*-
  106.  *-----------------------------------------------------------------------
  107.  * RmtSwapExit --
  108.  *    Byte-swap an Exit_Data structure.
  109.  *
  110.  * Results:
  111.  *    None.
  112.  *    
  113.  * Side Effects:
  114.  *    The words in the Exit_Data structure are byte-swapped.
  115.  *
  116.  *-----------------------------------------------------------------------
  117.  */
  118. static void
  119. RmtSwapExit(length, data)
  120.     int              length;
  121.     Exit_Data      *data;
  122. {
  123.     Rpc_SwapLong(sizeof(long), &data->id);
  124.     Rpc_SwapLong(sizeof(long), &data->status);
  125. }
  126.  
  127. static Boolean printEm = FALSE;    /* Set true if debugging and RmtCmpID
  128.                  * should print out the Job structures as it
  129.                  * checks them. */
  130.  
  131.  
  132. /*-
  133.  *-----------------------------------------------------------------------
  134.  * RmtCmpID --
  135.  *    See if a job is remote and has the given ID number
  136.  *
  137.  * Results:
  138.  *    0 if it matches, non-zero if it doesn't
  139.  *
  140.  * Side Effects:
  141.  *    None
  142.  *-----------------------------------------------------------------------
  143.  */
  144. static int
  145. RmtCmpID(job, id)
  146.     Job              *job;
  147.     unsigned long id;
  148. {
  149.     if (printEm) {
  150.     printf("\t%s: ", job->node->name);
  151.     if (job->flags & JOB_REMOTE) {
  152.         printf("remote #%d\n", ((CustomsPriv *)job->rmtID)->permit.id);
  153.     } else {
  154.         printf("local #%d\n", job->pid);
  155.     }
  156.     }
  157.     if (job->flags & JOB_REMOTE) {
  158.     return (id - ((CustomsPriv *)job->rmtID)->permit.id);
  159.     } else {
  160.     return(1);
  161.     }
  162. }
  163. /*-
  164.  *-----------------------------------------------------------------------
  165.  * RmtExit --
  166.  *    Handle a call on the returnFD to tell us a job has exited.
  167.  *
  168.  * Results:
  169.  *    Nothing.
  170.  *
  171.  * Side Effects:
  172.  *    A Job is finished out.
  173.  *    
  174.  *-----------------------------------------------------------------------
  175.  */
  176. static void
  177. RmtExit(from, msg, len, data)
  178.     struct sockaddr_in    *from;        /* Call from... */
  179.     Rpc_Message          msg;        /* Token for return */
  180.     int            len;        /* Length of passed data */
  181.     Rpc_Opaque        data;        /* Data passed */
  182. {
  183.     Exit_Data          *eData;        /* Data in our format */
  184.     register LstNode    ln;         /* Node of finished job */
  185.     register Job      *job;        /* The job itself */
  186.     union wait          status;        /* How it died */
  187.     CustomsPriv            *pdata;        /* Our private data */
  188.  
  189.     if (msg) {
  190.     /*
  191.      * Acknowledge the call
  192.      */
  193.     Rpc_Return(msg, 0, (Rpc_Opaque)0);
  194.     }
  195.  
  196.     eData = (Exit_Data *)data;
  197.     status.w_status = eData->status;
  198.  
  199.     if (WIFSTOPPED(status)) {
  200.     /*
  201.      * If the remote job has stopped, it must be because of us -- we've
  202.      * already continued it, therefore (or will, anyway), so there's no
  203.      * reason to slap the thing onto the stopped list and confuse things
  204.      * terribly...so we don't.
  205.      */
  206.     return;
  207.     }
  208.  
  209.     ln = Lst_Find(jobs, eData->id, RmtCmpID);
  210.     if (ln == NILLNODE) {
  211.     ln = Lst_Find(stoppedJobs, eData->id, RmtCmpID);
  212.     if (ln != NILLNODE) {
  213.         Error("Received exit for stopped job, id %d\n", eData->id);
  214.     } else {
  215.         Error("Received exit for unknown job id %d from %s\n", eData->id,
  216.           InetNtoA(from->sin_addr));
  217.         printEm = TRUE;
  218.         (void)Lst_Find(jobs, eData->id, RmtCmpID);
  219.         printEm = FALSE;
  220.     }
  221.     return;
  222.     }
  223.  
  224.     job = (Job *)Lst_Datum(ln);
  225.     pdata = (CustomsPriv *)job->rmtID;
  226.     if (!usePipes) {
  227.     /*
  228.      * Flush all data from the socket into the file before calling
  229.      * JobFinish
  230.      */
  231.     int    nb;
  232.     char      buf[512];
  233.     
  234.     while ((ioctl(pdata->rmtFd, FIONREAD, &nb) == 0) && (nb > 0)) {
  235.         if (nb > sizeof(buf)) {
  236.         nb = sizeof(buf);
  237.         }
  238.         nb = read(pdata->rmtFd, buf, nb);
  239.         (void)write(job->outFd, buf, nb);
  240.     }
  241.     (void)close(pdata->rmtFd);
  242.     }
  243.     
  244.     /*
  245.      * Take it out of the list
  246.      */
  247.     (void)Lst_Remove(jobs, ln);
  248.     nJobs -= 1;
  249.     
  250.     /*
  251.      * Table no longer full
  252.      */
  253.     jobFull = FALSE;
  254.     
  255.     /*
  256.      * Finish it out
  257.      */
  258.     free((char *)pdata);
  259.     JobFinish(job, status);
  260. }
  261.  
  262. /*-
  263.  *-----------------------------------------------------------------------
  264.  * RmtIO  --
  265.  *    Handle I/O transfers between a remote job and the local machine.
  266.  *
  267.  * Results:
  268.  *    Nothing.
  269.  *
  270.  * Side Effects:
  271.  *    None
  272.  *-----------------------------------------------------------------------
  273.  */
  274. static Boolean RmtBlockTimeout() { return (TRUE); }
  275. /*ARGSUSED*/
  276. static void
  277. RmtIO(stream, job, state)
  278.     int              stream;
  279.     Job          *job;
  280.     int          state;
  281. {
  282.     CustomsPriv        *pdata = (CustomsPriv *)job->rmtID;
  283.     
  284.     if (state & RPC_READABLE) {
  285.     if (usePipes) {
  286.         /*
  287.          * If we're using pipes, we can just use JobDoOutput to transfer
  288.          * the data to the screen.
  289.          */
  290.         JobDoOutput(job, FALSE);
  291.     } else {
  292.         /*
  293.          * Otherwise, we have to actually write the data to the output
  294.          * file. Just read a single 1K block each time through.
  295.          * Magic numbers R us.
  296.          */
  297.         char      buf[1024];
  298.         int        nb;
  299.  
  300.         nb = read(pdata->rmtFd, buf, sizeof(buf));
  301.         if (nb > 0) {
  302.         write(job->outFd, buf, nb);
  303.         }
  304.     }
  305.     }
  306.     if (state & RPC_WRITABLE) {
  307.     char      buf[512];
  308.     int       nb;
  309.  
  310.     nb = read(pdata->cmdFd, buf, sizeof(buf));
  311.     if (nb > 0) {
  312.         char  *cp;
  313.         struct timeval tv;
  314.         Rpc_Event ev;
  315.  
  316.         /*
  317.          * Stop watching for this stream to be writable until this buffer
  318.          * is written out
  319.          */
  320.         Rpc_Watch(pdata->rmtFd, RPC_READABLE, RmtIO, (ClientData)job);
  321.  
  322.         /*
  323.          * Write out the buffer in whatever chunks the socket can swallow
  324.          */
  325.         cp = buf;
  326.  
  327.         /*
  328.          * Create a timeout event to be invoked every 200 ms that makes
  329.          * sure Rpc_Wait will return with reasonable speed.
  330.          */
  331.         tv.tv_sec = 0;
  332.         tv.tv_usec = 200000;
  333.         ev = Rpc_EventCreate(&tv, RmtBlockTimeout, (Rpc_Opaque)0);
  334.         
  335.         while (nb > 0) {
  336.         int    cc = write(pdata->rmtFd, cp, nb);
  337.  
  338.         if (cc < 0) {
  339.             if (errno != EWOULDBLOCK) {
  340.             break;
  341.             } else {
  342.             cc = 0;
  343.             }
  344.         }
  345.         cp += cc;
  346.         nb -= cc;
  347.         if (nb > 0) {
  348.             /*
  349.              * Give other things a chance while we wait for the
  350.              * socket to drain enough.
  351.              */
  352.             Rpc_Wait();
  353.         }
  354.         }
  355.         Rpc_EventDelete(ev);
  356.         Rpc_Watch(pdata->rmtFd, RPC_READABLE|RPC_WRITABLE, RmtIO,
  357.               (ClientData)job);
  358.         
  359.         if (nb > 0) {
  360.         Exit_Data   eData;
  361.         
  362.         if (lastNode != job->node) {
  363.             printf(targFmt, job->node->name);
  364.             lastNode = job->node;
  365.         }
  366.         if (errno == EPIPE) {
  367.             printf("*** connection closed\n");
  368.         } else {
  369.             perror("*** writing to remote");
  370.         }
  371.         eData.id = pdata->permit.id;
  372.         eData.status = 1;
  373.         RmtExit((struct sockaddr_in *)0, (Rpc_Message)0,
  374.             sizeof(eData), (Rpc_Opaque)&eData);
  375.         }
  376.     } else {
  377.         if (nb < 0) {
  378.         perror("*** read(cmd)");
  379.         }
  380.         /*
  381.          * Nothing more to read, so force an EOF on the other side
  382.          * by doing an out-going shutdown, then only pay attention
  383.          * to the beast being readable.
  384.          */
  385.         shutdown(pdata->rmtFd, 1);
  386.         Rpc_Watch(pdata->rmtFd, RPC_READABLE, RmtIO, (Rpc_Opaque)job);
  387.     }
  388.     }
  389. }
  390.  
  391. /*-
  392.  *-----------------------------------------------------------------------
  393.  * RmtCheckChildren --
  394.  *    Timeout handler for seeing if anyone has died. Simply calls
  395.  *    Job_CatchChildren with block set to FALSE, then returns TRUE to
  396.  *    force Rpc_Wait to exit. This only happens if there are any
  397.  *    jobs running locally.
  398.  *
  399.  * Results:
  400.  *    TRUE.
  401.  *
  402.  * Side Effects:
  403.  *    Job_CatchChildren is called.
  404.  *    
  405.  *-----------------------------------------------------------------------
  406.  */
  407. static Boolean
  408. RmtCheckChildren()
  409. {
  410.     int        oldnj = nJobs;
  411.     
  412.     if (nLocal > 0) {
  413.     Job_CatchChildren(FALSE);
  414.     }
  415.  
  416.     return(oldnj != nJobs);
  417. }
  418.  
  419. /*-
  420.  *-----------------------------------------------------------------------
  421.  * Rmt_Signal --
  422.  *    Pass a signal to a job. The job module ensures the thing is remote
  423.  *
  424.  * Results:
  425.  *    None
  426.  *
  427.  * Side Effects:
  428.  *    An Rpc is issued to the server for the job to kill the thing
  429.  *    with the same signal.
  430.  *    
  431.  *-----------------------------------------------------------------------
  432.  */
  433. void
  434. Rmt_Signal(job, signo)
  435.     Job              *job;
  436.     int              signo;
  437. {
  438.     Kill_Data             packet;
  439.     struct sockaddr_in  server;
  440.     Rpc_Stat              rstat;
  441.     CustomsPriv            *pdata;
  442.  
  443.     pdata = (CustomsPriv *)job->rmtID;
  444.     
  445.     bzero(&server, sizeof(server));
  446.     server.sin_family =     AF_INET;
  447.     server.sin_addr =         pdata->permit.addr;
  448.     server.sin_port =         customs_AgentAddr.sin_port;
  449.  
  450.     packet.id =             pdata->permit.id;
  451.     packet.signo =          signo;
  452.  
  453.     rstat = Rpc_Call(customs_Socket, &server, (Rpc_Proc)CUSTOMS_KILL,
  454.              sizeof(packet), (Rpc_Opaque)&packet,
  455.              0, (Rpc_Opaque)0,
  456.              CUSTOMS_NRETRY, &customs_RetryTimeOut);
  457.     
  458.     if (rstat != RPC_SUCCESS) {
  459.     printf("sending signal %d to %s: %s\n", signo, job->node->name,
  460.            Rpc_ErrorMessage(rstat));
  461.     }
  462. }
  463.  
  464.  
  465. /*-
  466.  *-----------------------------------------------------------------------
  467.  * Rmt_Init --
  468.  *    Initialize this module...
  469.  *
  470.  * Results:
  471.  *    None.
  472.  *
  473.  * Side Effects:
  474.  *    The current working directory is placed in cwd and noAgent set
  475.  *    FALSE if the local customs agent could be contacted.
  476.  *
  477.  *-----------------------------------------------------------------------
  478.  */
  479. void
  480. Rmt_Init()
  481. {
  482.     Rpc_Stat      status;
  483.     struct timeval waitTime;    /* Interval at which to wake up to check for
  484.                  * dead children */
  485.  
  486.     if (noExport || ((status = Customs_Ping()) != RPC_SUCCESS)) {
  487.     if (DEBUG(RMT) && !noExport) {
  488.         printf("Could not contact customs agent: %s\n",
  489.            Rpc_ErrorMessage(status));
  490.     }
  491.     noAgent = TRUE;
  492.     } else {
  493.     if (DEBUG(RMT)) {
  494.         Rpc_Debug(1);
  495.     }
  496.  
  497.     noAgent = FALSE;
  498.         
  499.     Rpc_ServerCreate(customs_Socket, (Rpc_Proc)CUSTOMS_EXIT,
  500.              RmtExit, RmtSwapExit, Rpc_SwapNull,
  501.              (Rpc_Opaque)0);
  502.         
  503.     getwd(cwd);
  504.     if (DEBUG(RMT)) {
  505.         printf("Customs agent present. cwd = \"%s\"\n", cwd);
  506.     }
  507.         
  508.     signal (SIGPIPE, SIG_IGN); /* This isn't right. Should use signal
  509.                     * to check on remote jobs, or something. */
  510.     }
  511.     
  512.     /*
  513.      * Set up an event to check if any children have died.
  514.      */
  515.     waitTime.tv_sec = SEL_SEC;
  516.     waitTime.tv_usec = SEL_USEC;
  517.     (void)Rpc_EventCreate(&waitTime, RmtCheckChildren, (Rpc_Opaque)0);
  518. }
  519.  
  520. /*-
  521.  *-----------------------------------------------------------------------
  522.  * Rmt_AddServer --
  523.  *    Add a server to the list of those known.
  524.  *
  525.  * Results:
  526.  *    None.
  527.  *
  528.  * Side Effects:
  529.  *    None.
  530.  *
  531.  *-----------------------------------------------------------------------
  532.  */
  533. /*ARGSUSED*/
  534. void
  535. Rmt_AddServer (name)
  536.     char    *name;
  537. {
  538. }
  539. /*-
  540.  *-----------------------------------------------------------------------
  541.  * Rmt_Begin --
  542.  *    Prepare to export a job -- the Make-mode interface to Customs.
  543.  *
  544.  * Results:
  545.  *    TRUE if the job can be exported. FALSE if it cannot.
  546.  *
  547.  * Side Effects:
  548.  *    A TCP connection is opened to an available server and the
  549.  *    CUSTOMS_IMPORT command issued (i.e. the job is started
  550.  *    over there). exportFD is set to the fd of the connection and
  551.  *    returnFD to the fd of the socket to be used to return the exit
  552.  *    status.
  553.  *
  554.  *-----------------------------------------------------------------------
  555.  */
  556. /*ARGSUSED*/
  557. Boolean
  558. Rmt_Begin (file, argv, gn)
  559.     char          *file;
  560.     char          **argv;
  561.     GNode         *gn;
  562. {
  563.     if (noAgent) {
  564.     return (FALSE);
  565.     } else {
  566.     extern int errno;
  567.     int flags;
  568.  
  569.     returnFD = -1;
  570.     errno = 0;
  571.  
  572.     flags = ((gn->type & OP_EXPORTSAME) ? EXPORT_SAME : EXPORT_ANY)|
  573.         ((gn->type & OP_M68020) ? EXPORT_68020 : 0);
  574.     if (DEBUG(RMT)) {
  575.         printf("Rmt_Begin: flags = %d\n", flags);
  576.     }
  577.     exportFD = Customs_RawExport(file, argv, cwd,
  578.                      flags,
  579.                      &returnFD,
  580.                      &permit);
  581.     if (exportFD < 0) {
  582.         if (DEBUG(RMT)) {
  583.         perror("Customs_RawExport");
  584.         Customs_PError(file);
  585.         }
  586.         return (FALSE);
  587.     } else {
  588.         struct hostent *he;
  589.  
  590.         if (!beSilent) {
  591.         he = gethostbyaddr(&permit.addr,
  592.                    sizeof(permit.addr),
  593.                    AF_INET);
  594.         if (he == (struct hostent *)NULL) {
  595.             printf("*** exported to %s (id %u)\n",
  596.                InetNtoA(permit.addr),
  597.                permit.id);
  598.         } else {
  599.             printf("*** exported to %s (id %u)\n", he->h_name,
  600.                permit.id);
  601.         }
  602.         }
  603.         
  604.         return (TRUE);
  605.     }
  606.     }
  607. }
  608.  
  609. /*-
  610.  *-----------------------------------------------------------------------
  611.  * Rmt_Exec --
  612.  *    Execute a process elsewhere. If the exportation actually succeeded
  613.  *    (exportFD > 0), the "export" program is executed (must be on the
  614.  *    search path) with the -id flag.
  615.  *
  616.  * Results:
  617.  *    None.
  618.  *
  619.  * Side Effects:
  620.  *    That remains to be seen.
  621.  *
  622.  *-----------------------------------------------------------------------
  623.  */
  624. void
  625. Rmt_Exec (file, args, traceMe)
  626.     char    *file;
  627.     char    **args;
  628.     Boolean traceMe;
  629. {
  630.     if (exportFD > 0) {
  631.     char      fd1[4], fd2[4];
  632.     char      id[10];
  633.     char      *argv[6];
  634.  
  635.     sprintf (fd1, "%d", exportFD);
  636.     sprintf (fd2, "%d", returnFD);
  637.     sprintf (id, "%08x", permit.id);
  638.  
  639.     argv[0] = "export to";
  640.     argv[1] = "-id";
  641.     argv[2] = fd1;
  642.     argv[3] = fd2;
  643.     argv[4] = id;
  644.     argv[5] = (char *)0;
  645.     if (DEBUG(RMT)) {
  646.         printf("export -id %s %s %s\n", argv[2], argv[3], argv[4]);
  647.     }
  648.     (void)execvp ("export", argv);
  649.     if (DEBUG(RMT)) {
  650.         perror("Couldn't exec \"export\"");
  651.     }
  652.     } else {
  653.     if (DEBUG(RMT)) {
  654.         printf("Rmt_Exec called when exportFD == %d\n", exportFD);
  655.     }
  656.     (void)execvp (file, args);
  657.     }
  658. }
  659.  
  660. /*-
  661.  *-----------------------------------------------------------------------
  662.  * Rmt_Export --
  663.  *    Prepare to export a job -- the PMake-mode interface to customs.
  664.  *
  665.  * Results:
  666.  *    TRUE if the job can be exported. FALSE if it cannot.
  667.  *
  668.  * Side Effects:
  669.  *    A TCP connection is opened to an available server and the
  670.  *    CUSTOMS_IMPORT command issued (i.e. the job is started
  671.  *    over there). job->rmtFd is set to the fd of the connection and
  672.  *    job->permit to the permit under which the job is running. If
  673.  *    usePipes is TRUE, the pipes that were opened in JobStart are
  674.  *    closed again and job->inPipe is set to job->rmtFd to allow
  675.  *    us to use JobDoOutput to handle the output.
  676.  *
  677.  *-----------------------------------------------------------------------
  678.  */
  679. /*ARGSUSED*/
  680. Boolean
  681. Rmt_Export (file, argv, job)
  682.     char          *file;                /* File to exec */
  683.     char          **argv;               /* Arguments to it */
  684.     Job         *job;                    /* Job descriptor for it */
  685. {
  686.     if (noAgent) {
  687.     return (FALSE);
  688.     } else {
  689.     extern int errno;
  690.     struct timeval now, then;
  691.     int flags;
  692.     CustomsPriv *data = (CustomsPriv *)malloc(sizeof(CustomsPriv));
  693.  
  694.     errno = 0;
  695.     flags = ((job->node->type & OP_EXPORTSAME) ? EXPORT_SAME : EXPORT_ANY)|
  696.         ((job->node->type & OP_M68020) ? EXPORT_68020 : 0);
  697.  
  698.     if (DEBUG(RMT)) {
  699.         printf("Rmt_Export: flags = %d\n", flags);
  700.         gettimeofday(&now, 0);
  701.     }
  702.  
  703.     data->rmtFd = Customs_RawExport(file, argv, cwd, flags,
  704.                     &customs_Socket,
  705.                     &data->permit);
  706.     if (DEBUG(RMT)) {
  707.         gettimeofday(&then, 0);
  708.         then.tv_usec -= now.tv_usec;
  709.         if (then.tv_usec < 0) {
  710.         then.tv_usec += 1000000;
  711.         then.tv_sec -= now.tv_sec + 1;
  712.         } else {
  713.         then.tv_sec -= now.tv_sec;
  714.         }
  715.         printf("*** time spent calling: %d.%06d s\n",
  716.            then.tv_sec, then.tv_usec);
  717.     }
  718.  
  719.     if (data->rmtFd < 0) {
  720.         if (DEBUG(RMT)) {
  721.         perror("Customs_RawExport");
  722.         Customs_PError(file);
  723.         } else {
  724.         if (data->rmtFd > -100) {
  725.             if (usePipes) {
  726.             printf (targFmt, job->node->name);
  727.             lastNode = job->node;
  728.             }
  729.             printf("*** error calling local server: %s\n",
  730.                Rpc_ErrorMessage(-data->rmtFd));
  731.         } else switch(data->rmtFd) {
  732.         case CUSTOMS_NOEXPORT:
  733.             /*
  734.              * Just couldn't export -- no biggie.
  735.              */
  736.             break;
  737.         case CUSTOMS_NORETURN:
  738.             /*
  739.              * Couldn't create return socket
  740.              */
  741.             if (usePipes) {
  742.             printf (targFmt, job->node->name);
  743.             lastNode = job->node;
  744.             }
  745.             printf("*** error exporting: couldn't create return socket\n");
  746.             break;
  747.         case CUSTOMS_NONAME:
  748.             /*
  749.              * Couldn't fetch name of socket
  750.              */
  751.             if (usePipes) {
  752.             printf (targFmt, job->node->name);
  753.             lastNode = job->node;
  754.             }
  755.             printf("*** error exporting: couldn't find name of return socket\n");
  756.             break;
  757.         case CUSTOMS_ERROR:
  758.             if (usePipes) {
  759.             printf (targFmt, job->node->name);
  760.             lastNode = job->node;
  761.             }
  762.             printf("*** error exporting\n");
  763.             break;
  764.         case CUSTOMS_NOIOSOCK:
  765.             if (usePipes) {
  766.             printf(targFmt, job->node->name);
  767.             lastNode = job->node;
  768.             }
  769.             printf("*** error exporting: couldn't create I/O socket\n");
  770.             break;
  771.         default:
  772.             if (usePipes) {
  773.             printf (targFmt, job->node->name);
  774.             lastNode = job->node;
  775.             }
  776.             printf("*** error calling remote server: %s\n",
  777.                Rpc_ErrorMessage(-(data->rmtFd + 200)));
  778.             break;
  779.         }
  780.         fflush(stdout);
  781.         }
  782.         return (FALSE);
  783.     } else {
  784.         struct hostent *he;
  785.  
  786.         if (!(job->flags & JOB_SILENT)) {
  787.         he = gethostbyaddr(&data->permit.addr,
  788.                    sizeof(data->permit.addr),
  789.                    AF_INET);
  790.         if (usePipes) {
  791.             printf (targFmt, job->node->name);
  792.             lastNode = job->node;
  793.         }
  794.         
  795.         if (he == (struct hostent *)NULL) {
  796.             printf("*** exported to %s (id %u)\n",
  797.                InetNtoA(data->permit.addr),
  798.                data->permit.id);
  799.         } else {
  800.             printf("*** exported to %s (id %u)\n", he->h_name,
  801.                data->permit.id);
  802.         }
  803.         }
  804.         
  805.         if (usePipes) {
  806.         /*
  807.          * Close down the pipes that were opened for this job since
  808.          * we dinnae need them
  809.          */
  810.         (void)close(job->outPipe);
  811.         (void)close(job->inPipe);
  812.         job->outPipe = job->inPipe = data->rmtFd;
  813.         job->curPos = 0;
  814.         if (DEBUG(RMT)) {
  815.             printf("rmtFd = %d\n", data->rmtFd);
  816.         }
  817.         }
  818.         
  819.         fflush(stdout);
  820.  
  821.         fcntl(data->rmtFd, F_SETFL, FNDELAY);
  822.         fcntl(data->rmtFd, F_SETFD, 1);
  823.  
  824.         /*
  825.          * Record command file's descriptor and rewind the thing to its
  826.          * start.
  827.          */
  828.         data->cmdFd = fileno(job->cmdFILE);
  829.         lseek(data->cmdFd, 0, L_SET);
  830.  
  831.         /*
  832.          * Pay attention to the remote connection for two-way communication.
  833.          */
  834.         Rpc_Watch(data->rmtFd, RPC_READABLE|RPC_WRITABLE, RmtIO,
  835.               (Rpc_Opaque)job);
  836.  
  837.         /*
  838.          * Record the private data in the job record.
  839.          */
  840.         job->rmtID = (char *)data;
  841.         job->pid = 0;
  842.         
  843.         /*
  844.          * Success R Us
  845.          */
  846.         return (TRUE);
  847.     }
  848.     }
  849. }
  850.  
  851. /*-
  852.  *-----------------------------------------------------------------------
  853.  * Rmt_ReExport --
  854.  *    Supposed to re-export a job that's come home, but since jobs
  855.  *    can't come home under customs, we just return FALSE to say
  856.  *    we couldn't do it.
  857.  *
  858.  * Results:
  859.  *    FALSE.
  860.  *
  861.  * Side Effects:
  862.  *    None.
  863.  *
  864.  *-----------------------------------------------------------------------
  865.  */
  866. /*ARGSUSED*/
  867. Boolean
  868. Rmt_ReExport(pid)
  869.     int        pid;
  870. {
  871.     if (DEBUG(RMT)) {
  872.     printf("Rmt_ReExport called?\n");
  873.     }
  874.     return(FALSE);
  875. }
  876.  
  877. /*-
  878.  *-----------------------------------------------------------------------
  879.  * Rmt_LastID --
  880.  *    Return an unique identifier for the last job exported with Rmt_Exec
  881.  *
  882.  * Results:
  883.  *    Some sort of identifier. Just returns 1.
  884.  *
  885.  * Side Effects:
  886.  *    returnFD and exportFD are closed if we're in Make mode.
  887.  *
  888.  *-----------------------------------------------------------------------
  889.  */
  890. /*ARGSUSED*/
  891. int
  892. Rmt_LastID(pid)
  893.     int              pid;        /* PID of job last exported */
  894. {
  895.     if (amMake) {
  896.     (void)close(returnFD);
  897.     (void)close(exportFD);
  898.     exportFD = 0;
  899.     }
  900.     return (1);
  901. }
  902.  
  903. /*-
  904.  *-----------------------------------------------------------------------
  905.  * Rmt_Done --
  906.  *    Register the completion of a remote job.
  907.  *
  908.  * Results:
  909.  *    None.
  910.  *
  911.  * Side Effects:
  912.  *    None.
  913.  *
  914.  *-----------------------------------------------------------------------
  915.  */
  916. /*ARGSUSED*/
  917. void
  918. Rmt_Done (id)
  919.     int        id;
  920. {
  921. }
  922.  
  923. /*-
  924.  *-----------------------------------------------------------------------
  925.  * Rmt_Watch --
  926.  *    Watch a stream for the job module. It only requires us to
  927.  *    notify it of the readability of the stream.
  928.  *
  929.  * Results:
  930.  *    None
  931.  *
  932.  * Side Effects:
  933.  *    A call to Rpc_Watch is performed.
  934.  *    
  935.  *-----------------------------------------------------------------------
  936.  */
  937. void
  938. Rmt_Watch(stream, proc, data)
  939.     int        stream;         /* Stream to watch */
  940.     void    (*proc)();        /* Procedure to call */
  941.     char    *data;          /* Data to pass it when stream is ready */
  942. {
  943.     Rpc_Watch(stream, RPC_READABLE, proc, (Rpc_Opaque)data);
  944. }
  945.  
  946. /*-
  947.  *-----------------------------------------------------------------------
  948.  * Rmt_Ignore --
  949.  *    Pay no further attention to a stream
  950.  *
  951.  * Results:
  952.  *    None
  953.  *
  954.  * Side Effects:
  955.  *    Rpc_Ignore is called
  956.  *    
  957.  *-----------------------------------------------------------------------
  958.  */
  959. void
  960. Rmt_Ignore(stream)
  961.     int            stream;        /* Stream to ignore */
  962. {
  963.     Rpc_Ignore(stream);
  964. }
  965.  
  966. /*-
  967.  *-----------------------------------------------------------------------
  968.  * Rmt_Wait --
  969.  *    Wait for something to happen and return when it does
  970.  *
  971.  * Results:
  972.  *    None.
  973.  *
  974.  * Side Effects:
  975.  *    Those of the callback functions that are called.
  976.  *    
  977.  *-----------------------------------------------------------------------
  978.  */
  979. void
  980. Rmt_Wait()
  981. {
  982.     Rpc_Wait();
  983. }
  984.